home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 182_01 / rb_215.c < prev    next >
Text File  |  1990-07-30  |  18KB  |  817 lines

  1. #define VERSION "2.15 03-04-85"
  2.  
  3. /*% cc -DUSG -DNFGVMIN -O -K % -o rb
  4.  *
  5.  * rb.c By Chuck Forsberg
  6.  *
  7.  * A program for Unix which can receive
  8.  *  files from computers running YAM or MODEM.
  9.  *  If no filename is given, YAM batch mode is assumed.
  10.  *
  11.  * Iff the program is invoked by rbCOMMAND, output is piped to 
  12.  * "COMMAND filename"
  13.  *
  14.  *  Supports the CRC option or regular checksum.
  15.  *  Received pathnames containing no lowercase letters will be changed to lower
  16.  *  case unless -u option is given.
  17.  *
  18.  *  Unless the -b (binary) option is given, \r is discarded and
  19.  *  ^Z (which is also discarded) acts as end of file.
  20.  *
  21.  *  Any slashes in the pathname are changed to underscore.
  22.  *  If the raw pathname ends in .MSG or .TXT, any existing file will
  23.  *  be appended to rather than replaced. Trailing periods are eliminated.
  24.  *
  25.  *  If the raw pathname ends in any of the extensions in Extensions,
  26.  *   or .?Q* (squeezed file), or if the first sector contains binary-like
  27.  *   data (parity bits or characters in the range 0 to 6 before ^Z is seen),
  28.  *   or if the transmitted file mode has the 0100000 but set,
  29.  *   that file will be received in binary mode anyway.
  30.  *
  31.  *
  32.  * A log of activities is appended to LOGFILE with the -v option
  33.  * If stdout and stderr refer to different devices, progress is displayed to
  34.  * stderr.
  35.  *
  36.  * rb is derived from yam2.c and sb.c
  37.  * rb uses Unix System III buffered input to reduce CPU time.
  38.  *  USG UNIX (3.0) ioctl conventions courtesy  Jeff Martin
  39.  *     cc -O -DV7  rb.c -o rb        Unix V7, BSD 2.8 - 4.2
  40.  *    cc -O -DUSG rb.c -o rb        USG (3.0) Unix
  41.  *    cc -o rb.c            Regulus
  42.  *        (Don't try this on Unix, you'll clobber the source!)
  43.  *  Unix is a trademark of Western Electric Company
  44.  *
  45.  *  Regulus conventions 1-10-83 CAF
  46.  *
  47.  *  Some systems (Venix, Coherent, Regulus) do not support tty raw mode
  48.  *  read(2) the same way as Unix. ONEREAD must be defined to force one
  49.  *  character reads for these systems. Added 7-01-84 CAF
  50.  *
  51.  *  Alarm signal handling changed to work with 4.2 BSD 7-15-84 CAF 
  52.  *
  53.  *  NFGVMIN Added 1-13-85 CAF for PC-AT Xenix systems where c_cc[VMIN]
  54.  *  doesn't seem to work (even though it compiles without error!).
  55.  */
  56. #define LOGFILE "/tmp/rblog"
  57.  
  58. #include <stdio.h>
  59. #include <signal.h>
  60. #include <setjmp.h>
  61. #include <ctype.h>
  62. FILE *popen();
  63.  
  64. #define OK 0
  65. #define FALSE 0
  66. #define TRUE 1
  67. #define ERROR (-1)
  68.  
  69. #define HOWMANY 133
  70. #include "rbsb.c"    /* most of the system dependent stuff here */
  71.  
  72. char *substr();
  73. FILE *fout;
  74.  
  75. char *Extensions[] = {
  76. ".A",
  77. ".ARC",
  78. ".CCC",
  79. ".CL",
  80. ".CMD",
  81. ".COM",
  82. ".CRL",
  83. ".DAT",
  84. ".DIR",
  85. ".EXE",
  86. ".O",
  87. ".OBJ",
  88. ".OVL",
  89. ".PAG",
  90. ".REL",
  91. ".SAV",
  92. ".SUB",
  93. ".SWP",
  94. ".SYS",
  95. ".TAR",
  96. ".UTL",
  97. ".a",
  98. ".o",
  99. ".tar",
  100. ""
  101. };
  102.  
  103. /* Ward Christensen / CP/M parameters - Don't change these! */
  104. #define ENQ 005
  105. #define CAN ('X'&037)
  106. #define XOFF ('s'&037)
  107. #define XON ('q'&037)
  108. #define SOH 1
  109. #define STX 2
  110. #define EOT 4
  111. #define ACK 6
  112. #define NAK 025
  113. #define CPMEOF 032
  114. #define WANTCRC 0103    /* send C not NAK to get crc not checksum */
  115. #define TIMEOUT (-2)
  116. #define ERRORMAX 5
  117. #define RETRYMAX 5
  118. #define WCEOT (-10)
  119. #define SECSIZ 128    /* cp/m's Magic Number record size */
  120. #define PATHLEN 257    /* ready for 4.2 bsd ? */
  121. #define KSIZE 1024    /* record size with k option */
  122. #define UNIXFILE 0x8000    /* happens to the the S_IFREG file mask bit for stat */
  123.  
  124. int Lastrx;
  125. int Crcflg;
  126. int Firstsec;
  127. int Eofseen;        /* indicates cpm eof (^Z) has been received */
  128. int totblocks;        /* total number of blocks received */
  129. int errors;
  130.  
  131. #define DEFBYTL 2000000000L    /* default rx file size */
  132. long Bytesleft;        /* number of bytes of incoming file left */
  133. long Modtime;        /* Unix style mod time for incoming file */
  134. short Filemode;        /* Unix style mode for incoming file */
  135. char Pathname[PATHLEN];
  136. char *Progname;        /* the name by which we were called */
  137.  
  138. int Batch=0;
  139. int Wcsmask=0377;
  140. int Topipe=0;
  141. int MakeLCPathname=TRUE;    /* make received pathname lower case */
  142. int Verbose=0;
  143. int Quiet=0;        /* overrides logic that would otherwise set verbose */
  144. int Rxbinary=FALSE;    /* receive all files in bin mode */
  145. int Thisbinary;        /* current file is to be received in bin mode */
  146. int Blklen;        /* record length of received packets */
  147. char secbuf[KSIZE];
  148. char linbuf[KSIZE];
  149. int Lleft=0;        /* number of characters in linbuf */
  150.  
  151. jmp_buf tohere;        /* For the interrupt on RX timeout */
  152.  
  153. unsigned short updcrc();
  154.  
  155. alrm()
  156. {
  157.     longjmp(tohere, -1);
  158. }
  159.  
  160. /* called by signal interrupt or terminate to clean things up */
  161. bibi(n)
  162. {
  163.     canit(); mode(0);
  164.     fprintf(stderr, "sb: caught signal %d; exiting", n);
  165.     exit(128+n);
  166. }
  167.  
  168. main(argc, argv)
  169. char *argv[];
  170. {
  171.     register char *cp;
  172.     register npats;
  173.     char *virgin, **patts;
  174.     int exitcode;
  175.  
  176.     setbuf(stderr, NULL);
  177.     chkinvok(virgin=argv[0]);    /* if called as [-]rbCOMMAND set flag */
  178.     npats = 0;
  179.     while (--argc) {
  180.         cp = *++argv;
  181.         if (*cp == '-') {
  182.             while( *++cp) {
  183.                 switch(*cp) {
  184.                 case '1':
  185.                     iofd = 1; break;
  186.                 case '7':
  187.                     Wcsmask = 0177;
  188.                 case 'b':
  189.                     Rxbinary=TRUE; break;
  190.                 case 'k':
  191.                 case 'c':
  192.                     Crcflg=TRUE; break;
  193.                 case 'q':
  194.                     Quiet=TRUE; Verbose=0; break;
  195.                 case 'u':
  196.                     MakeLCPathname=FALSE; break;
  197.                 case 'v':
  198.                     ++Verbose; break;
  199.                 default:
  200.                     usage();
  201.                 }
  202.             }
  203.         }
  204.         else if ( !npats && argc>0) {
  205.             if (argv[0][0]) {
  206.                 npats=argc;
  207.                 patts=argv;
  208.             }
  209.         }
  210.     }
  211.     if (npats > 1)
  212.         usage();
  213.     if (Verbose) {
  214.         if (freopen(LOGFILE, "a", stderr)==NULL) {
  215.             printf("Can't open log file %s\n",LOGFILE);
  216.             exit(0200);
  217.         }
  218.         setbuf(stderr, NULL);
  219.         fprintf(stderr, "argv[0]=%s Progname=%s\n", virgin, Progname);
  220.     }
  221.     if (fromcu() && !Quiet) {
  222.         if (Verbose == 0)
  223.             Verbose = 2;
  224.     }
  225.     mode(1);
  226.     if (signal(SIGINT, bibi) == SIG_IGN) {
  227.         signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN);
  228.     }
  229.     else {
  230.         signal(SIGINT, bibi); signal(SIGKILL, bibi);
  231.     }
  232.     if (wcreceive(npats, patts)==ERROR) {
  233.         exitcode=0200;
  234.         canit();
  235.     }
  236.     mode(0);
  237.     if (exitcode != 0)    /* bellow again with all thy might. */
  238.         canit();
  239. #ifdef REGULUS
  240.     else
  241.         printf("\6\6\6\6\6\n");    /* Regulus doesn't wait ... */
  242. #endif
  243.     exit(exitcode);
  244. }
  245.  
  246.  
  247. usage()
  248. {
  249.     fprintf(stderr,"%s %s by Chuck Forsberg\n", Progname, VERSION);
  250.     fprintf(stderr,"Usage:    rb [-17buv]\n\tor rb [-1bcuv] file\n");
  251.     exit(1);
  252. }
  253.  
  254. wcreceive(argc, argp)
  255. char **argp;
  256. {
  257.     if (Batch || argc==0) {
  258.         Crcflg=(Wcsmask==0377);
  259.         fprintf(stderr, "rb: ready ");
  260.         for (;;) {
  261.             totblocks=0;
  262.             if (wcrxpn(secbuf)== ERROR)
  263.                 goto fubar;
  264.             if (secbuf[0]==0)
  265.                 return OK;
  266.             if (procheader(secbuf) == ERROR)
  267.                 goto fubar;
  268.             if (wcrx()==ERROR)
  269.                 goto fubar;
  270.         }
  271.     } else {
  272.         totblocks=0; Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;
  273.  
  274.         strcpy(Pathname, *argp);
  275.         if (fopen(*argp, "r") != NULL) {
  276.             fprintf(stderr, "rb: %s exists\n", Pathname);
  277.             goto fubar;
  278.         }
  279.         fprintf(stderr, "\nrb: ready to receive %s ", Pathname);
  280.         if ((fout=fopen(Pathname, "w")) == NULL)
  281.             return ERROR;
  282.         if (wcrx()==ERROR)
  283.             goto fubar;
  284.     }
  285.     return OK;
  286. fubar:
  287.     canit();
  288.     if (Topipe && fout) {
  289.         pclose(fout);  return ERROR;
  290.     }
  291.     if (fout)
  292.         fclose(fout);
  293.     return ERROR;
  294. }
  295.  
  296.  
  297. /*
  298.  * Fetch a pathname from the other end as a C ctyle ASCIZ string.
  299.  * Length is indeterminate as long as less than Blklen
  300.  * a null string represents no more files
  301.  */
  302. wcrxpn(rpn)
  303. char *rpn;    /* receive a pathname */
  304. {
  305.     register c;
  306.  
  307. #ifdef NFGVMIN
  308.     readline(1);
  309. #else
  310.     purgeline();
  311. #endif
  312.  
  313. et_tu:
  314.     Firstsec=TRUE;
  315.     sendline(Crcflg?WANTCRC:NAK);
  316.     while ((c = wcgetsec(rpn, 100)) != 0) {
  317.         log( "Pathname fetch returned %d\n", c);
  318.         if (c == WCEOT) {
  319.             sendline(ACK); readline(1); goto et_tu;
  320.         }
  321.         return ERROR;
  322.     }
  323.     sendline(ACK);
  324.     return OK;
  325. }
  326.  
  327. /*
  328.  * Adapted from CMODEM13.C, written by
  329.  * Jack M. Wierda and Roderick W. Hart
  330.  */
  331.  
  332. wcrx()
  333. {
  334.     register int sectnum, sectcurr;
  335.     register char sendchar;
  336.     register char *p;
  337.     int cblklen;            /* bytes to dump this block */
  338.     time_t timep[2];
  339.  
  340.     Firstsec=TRUE;sectnum=0; Eofseen=FALSE;
  341.     sendchar=Crcflg?WANTCRC:NAK;
  342.  
  343.     for (;;) {
  344.         sendl